package com.glacier.common.support.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.glacier.common.core.domain.BaseEntity;
import com.glacier.common.core.domain.Page;
import com.glacier.common.core.mapper.BaseMapper;
import com.glacier.common.core.service.BaseService;
import com.glacier.common.support.utils.MybatisBatchUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;

/**
 * date 2022-12-27 09:40
 *
 * @author glacier
 * @version 1.0.0
 */
public abstract class BaseServiceImpl<Mapper extends BaseMapper<T>,
    T extends BaseEntity> implements BaseService<T> {

    public final Logger LOGGER = LoggerFactory.getLogger(this.getClass());

    /**
     * 持久层对象
     */
    protected Mapper mapper;

    /**
     * mapper 类型
     */
    private final Class<Mapper> clz;

    /**
     * 批量处理工具类
     */
    protected MybatisBatchUtils mybatisBatchUtils;

    /**
     * 倍数
     */
    public static final int MULTIPLE = 2;

    /**
     * 批量处理 记录数
     */
    public static final int DEFAULT_BATCH_SIZE = 50;

    protected BaseServiceImpl(Class<Mapper> clz) {
        this.clz = clz;
    }

    /**
     * 设置依赖
     *
     * @param mapper
     */
    @Autowired
    public void setMapper(Mapper mapper) {
        this.mapper = mapper;
    }

    /**
     * 设置依赖
     *
     * @param mybatisBatchUtils
     */
    @Autowired
    public void setMybatisBatchUtils(MybatisBatchUtils mybatisBatchUtils) {
        this.mybatisBatchUtils = mybatisBatchUtils;
    }

    /**
     * 查询
     *
     * @param id
     * @return
     */
    @Transactional(readOnly = true)
    @Override
    public <ID extends Serializable> T findById(ID id) {
        return mapper.findById(id);
    }

    /**
     * 分页查询
     *
     * @param page
     * @param entity
     * @return
     */
    @Transactional(readOnly = true)
    @Override
    public Page<T> findPage(Page<T> page, T entity) {
        PageHelper.startPage(page.getPage(), page.getLimit());
        PageInfo<T> pageInfo = PageInfo.of(mapper.findList(entity));
        page.setTotal(pageInfo.getTotal());
        page.setData(pageInfo.getList());
        return page;
    }

    /**
     * 查询数据列表
     *
     * @param entity
     * @return
     */
    @Transactional(readOnly = true)
    @Override
    public List<T> findList(T entity) {
        return mapper.findList(entity);
    }

    /**
     * 保存
     *
     * @param entity
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int save(T entity) {
        int update;
        if (entity.isNewRecordFlag()) {
            // 设置为新增，防止钩子方法判断出错
            entity.setNewRecordFlag(true);
            // 设置主键
            entity.setId(StrUtil.blankToDefault(entity.getId(), IdUtil.fastSimpleUUID()));
            update = mapper.insert(entity);
        } else {
            update = mapper.update(entity);
        }
        return update;
    }

    /**
     * 删除
     *
     * @param entity
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int delete(T entity) {
        return mapper.delete(entity.getId());
    }

    /**
     * 删除
     * 批量处理里 已提交事务，注解事务失效。
     *
     * @param idList
     * @param <ID>
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public <ID extends Serializable> int batchDelete(List<ID> idList) {
        if (idList.isEmpty()) {
            return 0;
        }
        return mybatisBatchUtils.batchUpdateOrInsert(
            CollectionUtil.split(idList, DEFAULT_BATCH_SIZE),
            clz, (list, mapper1) -> mapper1.batchDelete(list));
    }
}
